package juc.executors;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

public class CompletableFutureExample2 {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        //supplyAsync();

        //Future<Void> future = runAsync();
        //future.get();

        //Future<Void> future = completed("hello");
        //System.out.println(future.isDone());

        //System.out.println(">>>" + anyOf().get());

        allOf();


        //使用join阻塞main线程
        Thread.currentThread().join();
    }

    private static void supplyAsync() throws InterruptedException {
        CompletableFuture.supplyAsync(Object::new)
                .thenAcceptAsync(o -> {
                    timeSleep(3);
                    System.out.println("===" + o);
                })
                .runAfterBoth(CompletableFuture.supplyAsync(() -> "hello")
                        .thenAcceptAsync(s -> {
                            timeSleep(2);
                            System.out.println("===" + s);
                        }), () -> {
                    System.out.println("finished");
                });
    }

    private static Future<Void> runAsync() throws InterruptedException {
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            timeSleep(3);
            System.out.println("===");
        }).whenComplete((v, t) -> System.out.println("over"));
        return future;
    }

    private static Future<Void> completed(String data) {
        return CompletableFuture.completedFuture(data).thenAccept(System.out::println);
    }

    private static Future<?> anyOf() {
        return CompletableFuture.anyOf(CompletableFuture.runAsync(
                () -> {
                    timeSleep(3);
                    System.out.println("1 ===");
                }
                ).whenComplete((v, t) -> System.out.println(v + "1 over")),
                CompletableFuture.supplyAsync(
                        () -> {
                            timeSleep(2);
                            System.out.println("2 ===");
                            return "hello";
                        }
                ).whenComplete((v, t) -> System.out.println(v + "2 over")),
                CompletableFuture.supplyAsync(
                        () -> {
                            timeSleep(2);
                            System.out.println("3 ===");
                            return "word";
                        }
                ).whenComplete((v, t) -> System.out.println(v + "3 over"))
        );

    }

    private static void allOf() {
        CompletableFuture.allOf(CompletableFuture.runAsync(
                () -> {
                    timeSleep(3);
                    System.out.println("1 ===");
                }
                ).whenComplete((v, t) -> System.out.println(v + "1 over")),
                CompletableFuture.supplyAsync(
                        () -> {
                            timeSleep(2);
                            System.out.println("2 ===");
                            return "hello";
                        }
                ).whenComplete((v, t) -> System.out.println(v + "2 over")),
                CompletableFuture.supplyAsync(
                        () -> {
                            timeSleep(2);
                            System.out.println("3 ===");
                            return "word";
                        }
                ).whenComplete((v, t) -> System.out.println(v + "3 over"))
        );

    }

    //不建议这样使用
    private static void create() {
        CompletableFuture<Object> future = new CompletableFuture<>();
        Object s = null;
        CompletableFuture.<Object>supplyAsync(() -> s);
    }


    /**
     * sleep the specify seconds
     */
    private static void timeSleep(long time) {
        try {
            TimeUnit.SECONDS.sleep(time);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
